﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kpmg.CompanyInfo;

namespace MySearch
{
    public static class ChargeableOM
    {
        public static Chargeable GetChargeable(string chargeCode, string profileCode)
        {
            if (string.IsNullOrEmpty(chargeCode) || string.IsNullOrEmpty(profileCode))
                throw new Exception("ChargeableOM.GetChargeable::Invalid parameter");

            Chargeable chargeable = ChargeableDAO.GetChargeable(chargeCode, profileCode);
            IList<CommonMember> lstMember = ChargeableDAO.ListChargeableMember(chargeCode);
            IList<CommonField> lstField = ChargeableDAO.ListChargeableField(chargeCode);
            foreach (CommonMember cm in lstMember)
                chargeable.AddMember(cm);
            foreach (CommonField cf in lstField)
                chargeable.AddField(cf);

            return chargeable;
        }

        public static Chargeable GetChargeable(string chargeCode)
        {
            if (string.IsNullOrEmpty(chargeCode))
                throw new Exception("ChargeableOM.GetChargeable::Invalid parameter");

            return ChargeableDAO.GetChargeable(chargeCode);
        }

        public static bool CheckChargeableCode(string chargeableCode, string profileCode)
        {
            if (string.IsNullOrEmpty(chargeableCode) || string.IsNullOrEmpty(profileCode))
                throw new Exception("ChargeableOM.CheckChargeableCode::Invalid parameter");

            return ChargeableDAO.CheckChargeableCode(chargeableCode, profileCode);
        }

        public static IList<Chargeable> ListMyChargeable(string staffNo)
        {
            if (string.IsNullOrEmpty(staffNo))
                throw new Exception("ChargeableOM.ListChargeable::Invalid parameter");

            IList<string> lstCode = ChargeableDAO.ListMyChargeableCode(staffNo);

            IList<Chargeable> list = new List<Chargeable>();
            foreach (string code in lstCode)
            {
                list.Add(ChargeableDAO.GetChargeable(code));
            }

            return list;
        }

        public static IList<Chargeable> ListProfileChargeable(string profileCode)
        {
            if (string.IsNullOrEmpty(profileCode))
                throw new Exception("ChargeableOM.ListProfileChargeable::Invalid parameter");

            IList<string> lstCode = ChargeableDAO.ListProfileChargeableCode(profileCode);

            IList<Chargeable> list = new List<Chargeable>();
            foreach (string code in lstCode)
            {
                list.Add(ChargeableDAO.GetChargeable(code));
            }

            return list;
        }

        public static void CreateChargeable(Chargeable obj, string oper)
        {
            if (obj == null || string.IsNullOrEmpty(oper))
                throw new Exception("ChargeableOM.CreateChargeable::Invalid parameter");

            //should not exist the ChargeableCode
            if (ChargeableDAO.CheckChargeableCode(obj.ChargeableCode, obj.ProfileCode))
                throw new Exception("ChargeableOM.CreateChargeable::Object exist");

            //should exist the ProfileCode
            if (!ProfileDAO.CheckProfileCode(obj.ProfileCode))
                throw new Exception("ChargeableOM.CreateChargeable::Object not exist");

            ChargeableDAO.CreateChargeable(obj);
            LogUtil.LogEvent(obj.ChargeableCode, EventAction.CreateChargeable, oper, obj.ToDictionary());
        }

        public static void UpdateChargeable(Chargeable chargeableNew, string oper, bool isSync = false)
        {
            if (chargeableNew == null || string.IsNullOrEmpty(oper))
                throw new Exception("ChargeableOM.UpdateChargeable::Invalid parameter");

            Chargeable objOld = ChargeableDAO.GetChargeable(chargeableNew.ChargeableCode, chargeableNew.ProfileCode);
            if (objOld == null)
                throw new Exception("ChargeableOM.UpdateChargeable::The object is null");

            IDictionary<string, string> chargeableDif = chargeableNew.FindDifference(objOld);
            if (!isSync)
                chargeableDif = chargeableDif.Where(x => x.Key != "IsMemberInherited").ToDictionary(y => y.Key, y => y.Value);

            IDictionary<string, string> memberDif = CheckMemDifference(chargeableNew, objOld, isSync);
            IDictionary<string, string> fieldDif = CheckDifference(chargeableNew.Fields.Select(x => x.Value).ToList(), objOld.Fields.Select(x => x.Value).ToList());

            if (chargeableDif.Count > 0)
            {
                ChargeableDAO.UpdateChargeable(chargeableNew, false);
                LogUtil.LogEvent(chargeableNew.ChargeableCode, EventAction.UpdateChargeable, oper, chargeableDif);
            }
            if (memberDif.Count > 0)
            {
                ChargeableDAO.UpdateMember(chargeableNew);
                LogUtil.LogEvent(chargeableNew.ChargeableCode, EventAction.UpdateChargeableMember, oper, memberDif);
            }
            if (fieldDif.Count > 0)
            {
                ChargeableDAO.UpdateField(chargeableNew);
                LogUtil.LogEvent(chargeableNew.ChargeableCode, EventAction.UpdateChargeableMember, oper, fieldDif);
            }
        }

        public static void SyncChargeableData(string oper)
        {
            IDictionary<string, Chargeable> dicChar = new Dictionary<string, Chargeable>();//PmsDataDAO.ListEngagements();

            try
            {
                foreach (KeyValuePair<string, Chargeable> objNew in dicChar)
                {
                    if (!ChargeableDAO.CheckChargeableCode(objNew.Key, objNew.Value.ProfileCode))
                    {
                        CreateChargeable(objNew.Value, oper);
                    }
                    else
                    {
                        UpdateChargeable(objNew.Value, oper, true);
                    }
                }
            }
            catch (Exception e)
            {
                LogUtil.LogEvent("Exception", EventAction.SyncChargeable, oper, e.ToString());
            }
        }



        #region private

        private static IDictionary<string, string> CheckDifference(IList<CommonField> lstNew, IList<CommonField> lstOld)
        {
            IDictionary<string, string> dicRet = new Dictionary<string, string>();

            foreach (CommonField cf in lstNew)
            {
                if (lstOld.Where(x => (x.Name == cf.Name && x.Value == cf.Value && x.DataType == cf.DataType)).Count() > 0)
                    continue;
                else
                {
                    string key = cf.Name;
                    if (!dicRet.ContainsKey(key))
                        dicRet.Add(key, cf.Value + "," + cf.DataType.ToString());
                }
            }

            return dicRet;
        }

        private static IDictionary<string, string> CheckMemDifference(Chargeable chargeableNew, Chargeable chargeableOld, bool isSync)
        {
            IDictionary<string, string> dicRet = new Dictionary<string, string>();

            if (isSync)
            {
                return dicRet;
            }
            else
            {
                IList<CommonMember> lstNew = chargeableNew.Members.Select(x => x.Value).ToList();
                IList<CommonMember> lstOld = chargeableOld.Members.Select(x => x.Value).ToList();

                foreach (CommonMember cm in lstNew)
                {
                    if (lstOld.Where(x => (x.StaffNo == cm.StaffNo && x.Role == cm.Role && x.Status == CommonStatus.Active)).Count() > 0)
                        continue;
                    else
                    {
                        CommonMember c = lstOld.Where(x => (x.StaffNo == cm.StaffNo && x.Role == cm.Role && x.Status == CommonStatus.Inactive)).FirstOrDefault();
                        if (c != null)
                        {
                            lstNew.Add(new CommonMember(c.StaffNo, c.Role, false, CommonStatus.Active));

                            string key = cm.StaffNo + "," + cm.Role.ToString();
                            if (!dicRet.ContainsKey(key))
                                dicRet.Add(key, "Inactive => Active");
                        }
                        else//Old not have, New have
                        {
                            string key = cm.StaffNo + "," + cm.Role.ToString();
                            if (!dicRet.ContainsKey(key))
                                dicRet.Add(key, "new member");
                        }
                    }
                }
            }

            return dicRet;
        }

        #endregion
    }
}
